home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / PowerTalk Access Modules / Sample SMSAM / SampleSMSAM Source / StatusMonitor / UDocumentSecondStomach.cp < prev    next >
Encoding:
Text File  |  1995-07-28  |  28.4 KB  |  1,100 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        UDocumentSecondStomach.cp
  3.  
  4.     Contains:    *** put contents here ***
  5.  
  6.     Written by:    Steve Datnow
  7.  
  8.     Copyright:    © 1992 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         8/25/93        ASB        When error in config dialogs show not dispose of dialog
  13.         8/18/93        SLD        Get popups working
  14.         8/17/93        SLD        Make checkboxes use longs and fix program error when 0 length config string is returned
  15.         4/2/93      KSS        Change the defn of status items from starting with •• to consisting of all lower case characters.
  16.         1/7/92      SLD        Created
  17.  
  18.     To Do:
  19. */
  20.  
  21.  
  22.  
  23. #ifndef __UDOCUMENTSecondStomach__
  24. #include "UDocumentSecondStomach.h"
  25. #endif
  26.  
  27. #ifndef __UWINDOW__
  28. #include "UWindow.h"
  29. #endif
  30.  
  31. #ifndef __UVIEWSERVER__
  32. #include <UViewServer.h>
  33. #endif
  34.  
  35. #ifndef __UPRINTING__
  36. #include <UPrinting.h>
  37. #endif
  38.  
  39. #ifndef __UMENUMGR__
  40. #include <UMenuMgr.h>
  41. #endif
  42.  
  43. #ifndef __ERRORS__
  44. #include <Errors.h>
  45. #endif
  46.  
  47. #ifndef __RESOURCES__
  48. #include <Resources.h>
  49. #endif
  50.  
  51. #ifndef __TOOLUTILS__
  52. #include <ToolUtils.h>
  53. #endif
  54.  
  55. #if false
  56. #ifndef __UCOMMANDSecondStomach__
  57. #include "UCommandSecondStomach.h"
  58. #endif
  59. #endif
  60.  
  61. #ifndef __UViewStatusInfo__
  62. #include "UViewStatusInfo.h"
  63. #endif
  64.  
  65. #ifndef __UGLOBALSSecondStomach__
  66. #include "UGlobalsSecondStomach.h"
  67. #endif
  68.  
  69. #ifndef __STDIO__
  70. #include <StdIO.h>
  71. #endif
  72.  
  73. /****************************** Constants ******************************/
  74.  
  75. const kSecondStomachWindowID = 1000;
  76.  
  77. /****************************** TDocumentSecondStomach ******************************/
  78.  
  79. long TDocumentSecondStomach::fUniqueSessionID = 0;
  80.  
  81. /***********************************|****************************************/
  82. #pragma segment AOpen
  83.  
  84. pascal void TDocumentSecondStomach::Initialize() // Override 
  85. {
  86.     inherited::Initialize();
  87. }
  88.  
  89. /***********************************|****************************************/
  90. OSErr GetTargetAddress (Str255& myPrompt, Str255& myAppStr, PortInfoRec& myPortInfo, AEAddressDesc& targetAddress,TargetID& toTargetID)
  91.  
  92. {
  93.     OSErr myErr;
  94.  
  95.     myErr = PPCBrowser((ConstStr255Param) myPrompt,(ConstStr255Param) myAppStr, FALSE,toTargetID.location,myPortInfo, nil, "");
  96.  
  97.     if (myErr == noErr)
  98.     {
  99.         toTargetID.name = myPortInfo.name;
  100.         return AECreateDesc(typeTargetID,(Ptr) &toTargetID, sizeof(toTargetID), targetAddress);
  101.     }
  102.     else
  103.         return myErr;
  104. }
  105.  
  106. /***********************************|****************************************/
  107. #pragma segment AOpen
  108.         
  109. pascal void TDocumentSecondStomach::IDocumentSecondStomach(TFile* itsFile,
  110.                                                 OSType itsCreator)
  111. {
  112.     fItemsToBeMonitored = nil;
  113.     //fSendAliveCounter = 0;
  114.     fTimerHandler= nil;
  115.     fStatusList = nil;
  116.     fDocSessionID = fUniqueSessionID++;
  117.     fLog = nil;
  118.     fStatus = nil;
  119.     fDisconnected = true;
  120.     
  121.     this->IFileBasedDocument(itsFile,itsCreator);
  122.     
  123.     TTimerHandler* theTimerHandler = new TTimerHandler();
  124.     FailNIL(theTimerHandler);
  125.     theTimerHandler->ITimerHandler(this);
  126.     theTimerHandler->SetIdleFreq(60);    // 5 seconds
  127.     gApplication->InstallCohandler((TEventHandler*) theTimerHandler, TRUE);
  128.     fTimerHandler = theTimerHandler;
  129.         
  130.     // SetIdleFreq(450);
  131. }
  132.  
  133. /***********************************|****************************************/
  134. #pragma segment AOpen
  135.  
  136. pascal OSErr TDocumentSecondStomach::EstablishSession()
  137. {
  138.     TAppleEvent* theMessage;
  139.     TAppleEvent* theReplyEvent = NULL;
  140.     
  141.     theMessage = new TAppleEvent;
  142.     theMessage->IAppleEvent(kSSEventClass, 'log ', fTargetAddress, kAEWaitReply);
  143.     theMessage->SetTimeoutVal(900);
  144.  
  145.     //    Send our sessionID to the application to be monitored in an AppleEvent.        
  146.     theMessage->WriteLong('SSID',fDocSessionID);
  147.     
  148.     // Two cases the Apple Event may time out or a bogus apple event may be returned
  149.     FailInfo fi;
  150.     if (fi.Try())
  151.     {
  152.         theReplyEvent = theMessage->Send();
  153.         fi.Success();
  154.     }
  155.     else
  156.     {
  157.         theMessage = (TAppleEvent*)  FreeIfObject((TObject*) theMessage);
  158.         if (fi.error != errAETimeout) 
  159.             return fi.error;
  160.     }
  161.     
  162.     //    Well, the send happened corrertly, so make sure that the other application
  163.     //    supports monitoring.
  164.     long willHandle = 0;
  165.     if (theReplyEvent) 
  166.         willHandle = theReplyEvent->ReadLong('SUPT');    // Make sure it is not a bogus reply
  167.  
  168.     theMessage = (TAppleEvent*)  FreeIfObject((TObject*) theMessage);
  169.     theReplyEvent = (TAppleEvent*)  FreeIfObject((TObject*) theReplyEvent);
  170.  
  171.     if (willHandle != cSupportMonitoring) {
  172.         return -1;
  173.     }
  174.     
  175.     MonitoringChange(false);
  176.     
  177.     return noErr;
  178. }
  179.  
  180. /***********************************|****************************************/
  181.  
  182. pascal void TDocumentSecondStomach::SendItemsToBeLogged()
  183. {
  184.     TAppleEvent* theMessage;
  185.  
  186.     TDynamicArray* theItemsToBeMonitored = fItemsToBeMonitored;
  187.     if (theItemsToBeMonitored != nil) {
  188.         FailNIL(theMessage = new TAppleEvent);
  189.         theMessage->IAppleEvent(kSSEventClass, 'itms', fTargetAddress, kAENoReply);        
  190.         theMessage->WriteLong('SSID',fDocSessionID);
  191.         theMessage->WritePtrList('INFO',typeLongInteger,theItemsToBeMonitored);
  192.         theMessage->Send();
  193.         theMessage = (TAppleEvent*)  FreeIfObject((TObject*) theMessage);
  194.         ResetTimer();
  195.     }
  196. }
  197.  
  198. /***********************************|****************************************/
  199. #pragma segment AClose
  200.  
  201. pascal void TDocumentSecondStomach::Disconnect() {
  202.     if ((fDisconnected == false)) {
  203.         TAppleEvent* theMessage;
  204.         FailNIL(theMessage = new TAppleEvent);
  205.         theMessage->IAppleEvent(kSSEventClass, 'stop', fTargetAddress, kAENoReply);        
  206.         theMessage->WriteLong('SSID',fDocSessionID);
  207.         FailInfo fi;
  208.         if (fi.Try())
  209.         {
  210.             theMessage->Send();    // Don't care if we fail
  211.             fi.Success();
  212.         }
  213.         
  214.         theMessage = (TAppleEvent*)  FreeIfObject((TObject*) theMessage);
  215.         fDisconnected = true;
  216.     }
  217. }
  218.  
  219. pascal void TDocumentSecondStomach::Free() // Override 
  220. {
  221.  
  222.     Disconnect();
  223.     
  224.     if (fTimerHandler) {
  225.         gApplication->InstallCohandler((TEventHandler*) fTimerHandler, FALSE);
  226.         fTimerHandler = (TTimerHandler*)  FreeIfObject((TObject*) fTimerHandler);
  227.     }
  228.     
  229.     fStatusList = (TStatusItemList*)  FreeListIfObject((TList*) fStatusList);
  230.     fItemsToBeMonitored  = (TDynamicArray*)  FreeIfObject((TObject*) fItemsToBeMonitored);
  231.     
  232.     inherited::Free();
  233. }
  234.  
  235. /***********************************|****************************************/
  236. #pragma segment AClose
  237.  
  238. pascal void TDocumentSecondStomach::FreeData() // Override 
  239. {
  240.     inherited::FreeData();
  241. }
  242.  
  243. /***********************************|****************************************/
  244. #pragma segment AOpen
  245.  
  246. pascal void TDocumentSecondStomach::DoInitialState() // Override 
  247. {
  248.     inherited::DoInitialState();
  249.     fItemsToBeMonitored = nil;
  250.     fReOpening = false;
  251. }
  252.  
  253. /***********************************|****************************************/
  254. #pragma segment AOpen
  255.  
  256. /***********************************|****************************************/
  257.  
  258. pascal CompareResult CompareIDs(TObject* anItem, void* staticLink)
  259.  
  260. {
  261.     long e1 = ((TStatusItem*)anItem)->GetID();
  262.     long e2 = (long) staticLink;
  263.     
  264.     if (e1 == e2) 
  265.         return kItem1EqualItem2;
  266.     else
  267.         if (e1 < e2)
  268.             return kItem1LessThanItem2;
  269.         else
  270.             return kItem1GreaterThanItem2;
  271. }
  272.  
  273. /***********************************|****************************************/
  274.  
  275. Boolean IsCharLegalInViewIdentifier ( char c )
  276. {
  277.     return ! (( c >= 'a' ) && ( c <= 'z' ) || (c == ' '));
  278. }
  279.  
  280. /***********************************|****************************************/
  281.  
  282. Boolean IsViewIdentifierAStatusItem ( IDType viewType )
  283. {    unsigned long l = (unsigned long) viewType;
  284.     char c1 = (char) ((l & (unsigned long) 0xff000000) >> 24);
  285.     char c2 = (char) ((l & (unsigned long) 0x00ff0000) >> 16);
  286.     char c3 = (char) ((l & (unsigned long) 0x0000ff00) >>  8);
  287.     char c4 = (char) ((l & (unsigned long) 0x000000ff) >>  0);
  288.  
  289.     Boolean result = (IsCharLegalInViewIdentifier(c1) ) && (IsCharLegalInViewIdentifier(c2) ) &&
  290.                      (IsCharLegalInViewIdentifier(c3) ) && (IsCharLegalInViewIdentifier(c4) &&
  291.                      ((c1 != 'V') || (c2 != 'W')) );
  292.     
  293.     return result;
  294. }
  295.  
  296. /***********************************|****************************************/
  297.  
  298. pascal void BuildStatusTable(TView* theSubView, void* staticLink)
  299. {
  300. //    IDType t = theSubView->fIdentifier;
  301.     char identifierStr[5];
  302.     * ( long *) &identifierStr[0] = theSubView->fIdentifier;
  303.     identifierStr[4] = 0;
  304.  
  305.     if (IsViewIdentifierAStatusItem ( theSubView->fIdentifier ) )
  306.     {
  307.         //    Find whether this item is already in our list of identifiers
  308.         TStatusItemList* theList = (TStatusItemList*) staticLink;
  309.         TStatusItem* aStatusItem = (TStatusItem*) theList->Search(&CompareIDs, (void*) theSubView->fIdentifier);
  310.         
  311.         //    If it's not already in the list, create a new statusItem and save it in
  312.         //    the list.
  313.         if (aStatusItem == nil) {
  314.             // fprintf (stderr, "BuildStatusTable::'%s' is being added.\n", identifierStr);
  315.             
  316.             aStatusItem = new TStatusItem;
  317.             aStatusItem->SetID(theSubView->fIdentifier);
  318.             aStatusItem->SetDescType(typeWildCard);
  319.             
  320.             theList->Insert((TObject*) aStatusItem); 
  321.          }
  322.         else
  323.         {
  324.             // fprintf (stderr, "BuildStatusTable::'%s' is already in table.\n", identifierStr);
  325.         }
  326.         
  327.         //    And make this view item depend on this status item.
  328.         aStatusItem->AddDependent((TObject*) theSubView);
  329.         aStatusItem->SetInfo(NULL,0,typeWildCard);
  330.     }
  331.     else
  332.     {
  333.         // fprintf (stderr, "BuildStatusTable::'%s' is not a legal identifier.\n", identifierStr);
  334.     }
  335.  
  336.     theSubView->EachSubView (BuildStatusTable, (void*) staticLink );
  337. }
  338.  
  339. /***********************************|****************************************/
  340.  
  341. pascal void AddToList(TObject* item, void* staticLink) 
  342. {
  343.     TStatusItem* theStatusItem = (TStatusItem*) item;
  344.     IDType theID = theStatusItem->GetID();
  345.     TDynamicArray* theItemsToBeMonitored = (TDynamicArray*) staticLink;
  346.     theItemsToBeMonitored->InsertElementsBefore(theItemsToBeMonitored->GetSize()+1,(Ptr) &theID,1);
  347. }
  348.  
  349. /***********************************|****************************************/
  350.  
  351. void PrintViewAndSubview ( TView * aView , unsigned long depth = 0)
  352. {
  353.     char viewIDStr[8];
  354.     * ( long *) &viewIDStr[0] = aView->fIdentifier;
  355.     viewIDStr[4] = 0;
  356.  
  357.     #if 0
  358.     for (unsigned long i = 0; i < depth; ++i)
  359.         fprintf (stderr, "  ");
  360.     fprintf (stderr, "View: '%s'  (%d children)\n", viewIDStr, aView->CountSubViews());
  361.  
  362.     CSubViewIterator anIterator ( aView );
  363.     for (unsigned long count = 1; count <= aView->CountSubViews(); ++count) {
  364.         TView* childView = (TView*) aView->fSubViews->At(count);
  365.         
  366.         char childIDStr[8];
  367.         * ( long *) &childIDStr[0] = childView->fIdentifier;
  368.         childIDStr[4] = 0;
  369.     
  370.         for (i = 0; i < depth; ++i)
  371.             fprintf (stderr, "  ");    
  372.         fprintf (stderr, "%2d. '%s' (%d children)\n", count, childIDStr, childView->CountSubViews());
  373.     }
  374.     #endif
  375.     
  376.     CSubViewIterator anIterator2 ( aView );
  377.     for (TView* childView = anIterator2.FirstSubView(); anIterator2.More(); childView = anIterator2.NextSubView())
  378.         PrintViewAndSubview ( childView , depth + 1);
  379.  
  380. //    for (i = 0; i < depth; ++i)
  381. //        fprintf (stderr, "  ");
  382. //    fprintf (stderr, "View: '%s' DONE\n", viewIDStr, aView->CountSubViews());
  383.  
  384. }
  385.  
  386. /***********************************|****************************************/
  387.  
  388. pascal void TDocumentSecondStomach::DoMakeViews(Boolean /*forPrinting*/) // Override 
  389. {
  390.     TWindow* aWindow = NULL;
  391.     TStdPrintHandler* aHandler = NULL;
  392.     TView* aView = NULL;
  393.  
  394.     TStatusItemList* statusList = new TStatusItemList;
  395.     statusList->IList();
  396.         
  397.  
  398.     FailInfo fi;
  399.     if (fi.Try())
  400.     {
  401.         FailNIL(aWindow = gViewServer->NewTemplateWindow(kSecondStomachWindowID, this));
  402.         
  403.         AEAddressDesc theTargetAddress;
  404.         PortInfoRec thePortInfoRec;
  405.         TargetID theTargetID;
  406.         Str255 temp;
  407.         OSErr err;
  408.         
  409.         temp[0] = 0;
  410.     
  411.         if (fReOpening) {
  412.             theTargetID = fTargetID;
  413.             err = AECreateDesc(typeTargetID,(Ptr) &theTargetID, sizeof(theTargetID), theTargetAddress);
  414.         }
  415.         else {
  416.             // Call up the PPC browser to find gateway
  417.             err = GetTargetAddress(temp, temp, thePortInfoRec, theTargetAddress, theTargetID);
  418.         }
  419.         
  420.         if (err == userCanceledErr)
  421.             Failure(noErr,messageCancelled);
  422.         else
  423.             FailOSErr(err);
  424.             
  425.         fTargetID = theTargetID;
  426.         fTargetAddress = theTargetAddress;
  427.         
  428.         Handle h = GetResource('mWin',1000);
  429.         short x = (short) *((long*) (*h));
  430.         short y = (short)  *((long*) (*h+4));
  431.         CPoint itsMinSize = CPoint(x,y);
  432.     
  433.         CPoint itsMaxSize = CPoint((short) aWindow->fSize.h,(short) aWindow->fSize.v);
  434.         aWindow->SetResizeLimits(itsMinSize,itsMaxSize);
  435.         
  436.         if (fReOpening == true) {
  437.             aWindow->SetFrame(fWinFrame,kDontRedraw);
  438.             aWindow->ForceOnScreen();
  439.             fReOpening = false;
  440.         }
  441.         else {
  442.             VRect frame;
  443.             SetChangeCount(1);    // Save menu items active now
  444.             aWindow->GetFrame(frame);
  445.             fWinFrame = frame;
  446.         }
  447.         
  448.         aView = (TView*) (aWindow->FindSubView('scrl'));    // Must cast because FindSubView returns TView
  449.         FailNIL(aView);
  450.             
  451.         aHandler = new TStdPrintHandler;
  452.         aHandler->IStdPrintHandler(this,            // its document 
  453.                                    aView,    // its view 
  454.                                    !kSquareDots,    // does not have square dots 
  455.                                    kFixedSize,        // horzontal page size is fixed 
  456.                                    kFixedSize);        // vertical page size is fixed
  457.  
  458.  
  459.         PrintViewAndSubview ( aView );
  460.  
  461.                                    
  462.         aView->EachSubView(BuildStatusTable, (void*) statusList);
  463.         fStatusList = statusList;
  464.         TDynamicArray* theItemsToBeMonitored;
  465.         FailNIL(theItemsToBeMonitored = new TDynamicArray());
  466.         theItemsToBeMonitored->IDynamicArray(statusList->GetSize(),sizeof(long));
  467.         statusList->Each(&AddToList,(void*) theItemsToBeMonitored);
  468.         fItemsToBeMonitored = theItemsToBeMonitored;
  469.             
  470.         if (aWindow != nil) {
  471.             fStatus = (TViewMonitorStatus*) (aWindow->FindSubView('stus'));
  472.         }
  473.             
  474.         fLog = (TViewlogStatusInfo*) (aView->FindSubView( 'GLOG'));
  475.         AddToLog("Monitor Started");
  476.         
  477.         err = EstablishSession();
  478.         if (err != noErr) {
  479.             SysBeep(5);
  480.             MonitoringChange(true);
  481.         }
  482.         else
  483.             SendItemsToBeLogged();
  484.     
  485.         fi.Success();
  486.     }
  487.     else
  488.     {
  489.         fi.ReSignal();
  490.     };    
  491. }
  492.  
  493. /***********************************|****************************************/
  494. #pragma segment AWriteFile
  495.  
  496. pascal void TDocumentSecondStomach::DoNeedDiskSpace(TFile* itsFile,
  497.                                         long& dataForkBytes,
  498.                                         long& rsrcForkBytes) // Override 
  499. {
  500.     inherited::DoNeedDiskSpace(itsFile, dataForkBytes, rsrcForkBytes);
  501. }
  502.  
  503. /***********************************|****************************************/
  504. #pragma segment ASelCommand
  505.  
  506. pascal void TDocumentSecondStomach::DoMenuCommand(CommandNumber aCommandNumber) // Override 
  507. {
  508. /*
  509. This method is overridden to handle menu items which are enabled when this document
  510. is in the target chain. In this example, this is true when the document is open and
  511. its window is the active window. The inherited method should always be called so 
  512. that MacApp can allow successor objects in the target chain (i.e. the application) to 
  513. handle THEIR menu items.
  514. */
  515.     switch (aCommandNumber) 
  516.     {
  517.         case 2001:
  518.             {
  519.                 TWindow *    aWindow;
  520.                 IDType        dismisser;
  521.  
  522.                 FailNIL(aWindow = gViewServer->NewTemplateWindow(1001, this));
  523.                 dismisser = aWindow->PoseModally();
  524.                 aWindow->CloseAndFree();                
  525.             }
  526.             break;    
  527.         case 4000:case 4002:
  528.             {
  529.                 TWindow *    aWindow;
  530.                 IDType        dismisser;
  531.  
  532.                 FailNIL(aWindow = gViewServer->NewTemplateWindow(aCommandNumber, this));
  533.                 dismisser = aWindow->PoseModally();
  534.                 aWindow->CloseAndFree();                
  535.             }
  536.             break;    
  537.  
  538.         default:
  539.             inherited::DoMenuCommand(aCommandNumber);
  540.             break;
  541.     }
  542. }
  543.  
  544. /***********************************|****************************************/
  545. #pragma segment AReadFile
  546.  
  547. pascal void TDocumentSecondStomach::DoRead(TFile* aFile,
  548.                                        Boolean forPrinting) // Override 
  549. {
  550.     TargetID theTID;
  551.     
  552.     inherited::DoRead(aFile,forPrinting);
  553.     VRect winFrame;
  554.     long theSize = sizeof(winFrame);
  555.     FailOSErr(aFile->ReadData(&winFrame,theSize));    // Window position
  556.     theSize = sizeof(theTID);
  557.     FailOSErr(aFile->ReadData(&theTID,theSize));    // Target being monitored
  558.     fWinFrame = winFrame;
  559.     fTargetID = theTID;
  560.  
  561.     fReOpening = true;
  562. }
  563. /***********************************|****************************************/
  564. #pragma segment ARes
  565.  
  566. pascal void TDocumentSecondStomach::DoSetupMenus() // Override 
  567. {
  568. /*
  569. This method is overridden to enable menu items which should be enabled when this 
  570. object is in the target chain. MacApp initially disables all menu items, then
  571. lets the objects in the target chain enable those items they handle. 
  572.  
  573. A document object is in the target chain when its window is the active window.
  574.  
  575. The inherited method is called so that TDocument can enable document-level menu items
  576. like "Save…". This also ensures that objects further up the target chain (the application)
  577. can set up THEIR menus. 
  578. */
  579.     inherited::DoSetupMenus();
  580.     
  581.     //Enable(2001,TRUE);
  582.     Enable(4000,TRUE);
  583.     Enable(4002,TRUE);
  584. }
  585.  
  586. /***********************************|****************************************/
  587. #pragma segment AWriteFile
  588.  
  589. pascal void TDocumentSecondStomach::DoWrite(TFile* aFile,
  590.                                     Boolean makingCopy) // Override 
  591. {
  592.     inherited::DoWrite(aFile,makingCopy);
  593.     long theSize = sizeof(VRect);
  594.     VRect winSize;
  595.     TargetID tID;
  596.     
  597.     TWindow* window = (TWindow*) fWindowList->At(1);
  598.     window->GetFrame(winSize);
  599.     FailOSErr(aFile->WriteData(&winSize,theSize));
  600.     
  601.     tID = fTargetID;
  602.     theSize = sizeof(tID);
  603.     FailOSErr(aFile->WriteData(&tID,theSize));
  604. }
  605.  
  606. /***********************************|****************************************/
  607.  
  608. pascal long  TDocumentSecondStomach::GetSessionID()
  609.     
  610. {
  611.     return fDocSessionID;
  612. }
  613.  
  614. /***********************************|****************************************/
  615.  
  616. pascal void GetUpdatedValue(TObject* anItem, void* staticLink) {
  617.     TAppleEvent* theMessage = (TAppleEvent*) staticLink;
  618.     TStatusItem* statusItem = (TStatusItem*) anItem;
  619.     CStr255 newData;
  620.     long newDataSize;
  621.     DescType actualType;
  622.     DescType desiredType = typeWildCard;
  623.     
  624.     FailInfo fi;
  625.     if (fi.Try())
  626.     {
  627.         theMessage->ReadParameterPtr(statusItem->GetID(),
  628.                                 typeWildCard,
  629.                                 actualType,
  630.                                 (Ptr) &newData,
  631.                                 sizeof(newData),
  632.                                 newDataSize);
  633.  
  634.         {    char    idStr[8];
  635.             * (OSType*) idStr = statusItem->GetID();
  636.             idStr[4] = 0;
  637.         
  638.             newData[newData[0]] = 0;    
  639.             //    fprintf (stderr, "GetUpdatedValue: '%s' = '%s'\n", idStr, (char*) &newData[1]);
  640.         }
  641.  
  642.         statusItem->SetInfo((void*) &newData, newDataSize, actualType);
  643.  
  644.         fi.Success();
  645.     }
  646.     else
  647.     {
  648.         if (fi.error != errAEDescNotFound) 
  649.             fi.ReSignal();
  650.     };
  651. }
  652.  
  653. /***********************************|****************************************/
  654.  
  655. pascal void TDocumentSecondStomach::MonitoringChange(Boolean stopMonitoring) 
  656.  
  657. {
  658.     if (fWindowList->GetSize() > 0) {
  659.         if (stopMonitoring == false) { 
  660.             fDisconnected = false;
  661.             SetStatus("");
  662.         }
  663.         else {
  664.             SetStatus("Not Responding");
  665.             AddToLog("Unable to Monitor");
  666.             fDisconnected = true;
  667.         }
  668.         
  669.         Boolean done = false;
  670.         CStr255 logID;
  671.         TView* aView;
  672.         TControl* tView;
  673.         TWindow* aWindow;
  674.         short index = 1;
  675.     
  676.         aWindow = (TWindow*) fWindowList->At(1);
  677.         FailNIL( aWindow );
  678.             
  679.         aView = (TView*) (aWindow->FindSubView('scrl'));    
  680.         if (aView == nil)
  681.             FailNIL(aView);
  682.         
  683.         /* This Grays any views that we want grayed when disconnected */
  684.         
  685.         while (done == false) {
  686.             GetIndString(logID, kViewsToGreyWhenDisconnected, index);
  687.         
  688.             if (logID.Length() == 4) {
  689.                 tView = (TControl*) (aView->FindSubView( * ((long*) (&logID[1]))));
  690.                 if (tView)
  691.                     tView->DimState(stopMonitoring, kRedraw);
  692.             }
  693.             else
  694.                 done = true;
  695.                 
  696.             index++;
  697.         }
  698.     }
  699. }
  700.  
  701. /***********************************|****************************************/
  702.  
  703. pascal void TDocumentSecondStomach::HandleStatusInfo(TAppleEvent* theMessage) {
  704.     if (fStatusList) {
  705.         fStatusList->Each(&GetUpdatedValue, (void*) theMessage);
  706.         ResetTimer();
  707.     
  708.         if (fDisconnected == true) {
  709.             MonitoringChange(false);
  710.         }
  711.     }
  712. }
  713.  
  714. /***********************************|****************************************/
  715.  
  716. pascal void  TDocumentSecondStomach::ResetTimer()
  717.  
  718. {
  719.     unsigned long secs;
  720.     GetDateTime(secs);
  721.     fHeartBeat = secs;
  722. }
  723.  
  724. /***********************************|****************************************/
  725.  
  726. pascal Boolean TDocumentSecondStomach::TimerExpired()
  727.  
  728. {
  729.     // This should be greater then the interval between updates from the server (30)
  730.     const unsigned long kSecondsBetweenChecks = 45; 
  731.     unsigned long secs;
  732.     
  733.     GetDateTime(secs);
  734.     if ((secs - fHeartBeat) > kSecondsBetweenChecks) {    
  735.         return true;
  736.     }
  737.     else {
  738.         return false;
  739.     }
  740. }
  741.  
  742. /***********************************|****************************************/
  743.  
  744. pascal void TDocumentSecondStomach::BlinkStatus() 
  745.  
  746. {
  747.     if (fStatus != nil)
  748.         fStatus->BlinkText();
  749. }
  750.  
  751. /***********************************|****************************************/
  752.  
  753. pascal void TDocumentSecondStomach::SetStatus(CStr255 message)
  754. {
  755.     if (fStatus != nil)
  756.         fStatus->SetText(message, kRedraw);
  757. }
  758.  
  759. /***********************************|****************************************/
  760.  
  761. pascal void TDocumentSecondStomach::AddToLog(CStr255 message)
  762.  
  763. {
  764.     if (fLog != nil) {
  765.         fLog->AddToLog(message);
  766.     }
  767. }
  768. /***********************************|****************************************/
  769.  
  770. pascal Boolean TDocumentSecondStomach::DoIdle(IdlePhase)
  771. {
  772.     return FALSE;
  773. }
  774.  
  775. /***********************************|****************************************/
  776.  
  777. pascal void TDocumentSecondStomach::SendButtonMessage(long buttonId)
  778.  
  779. {
  780.         TAppleEvent* theMessage;
  781.         FailNIL(theMessage = new TAppleEvent);
  782.         theMessage->IAppleEvent(kSSEventClass, 'butt', fTargetAddress, kAENoReply);    
  783.         theMessage->WriteLong('SSID',fDocSessionID);
  784.         theMessage->WriteLong('MCMD',buttonId);
  785.         FailInfo fi;
  786.         if (fi.Try())
  787.         {
  788.             theMessage->Send();    // Don't care if we fail
  789.             fi.Success();
  790.         }
  791.         else
  792.         {
  793.         }
  794.         
  795.         theMessage = (TAppleEvent*)  FreeIfObject((TObject*) theMessage);
  796. }
  797.  
  798. pascal void TDocumentSecondStomach::SendConfigMessage(TView* theView) {
  799.         TAppleEvent* theMessage;
  800.         TAppleEvent* theReplyEvent = NULL;
  801.         CStr255 configParam;
  802.         short configIndex;
  803.         long checkValue;
  804.         
  805.         const kConfigStringList = 7000;
  806.         
  807.         /* Get user value */
  808.         configIndex = theView->fUserArea;
  809.         
  810.         /* Get the config parameter name */
  811.         GetIndString(configParam,kConfigStringList,configIndex);
  812.  
  813.         FailNIL(theMessage = new TAppleEvent);
  814.         theMessage->IAppleEvent(kSSEventClass, 'sfig', fTargetAddress, kAEWaitReply);    
  815.         theMessage->WriteLong('SSID',fDocSessionID);
  816.         
  817.         /* Write config parameter to outgoing ae */ 
  818.         theMessage->WriteString('WFIG',configParam);
  819.         
  820.         if (theView->IsMemberClass(GetClassIDFromName("TEditText"))) {
  821.             ((TEditText*) theView)->GetText(configParam);
  822.             theMessage->WriteString('FIGV', configParam);
  823.         }
  824.         else if (theView->IsMemberClass(GetClassIDFromName("TCheckBox"))) {
  825.                 if (((TCheckBox*) theView)->IsOn())
  826.                     checkValue = 1;
  827.                 else
  828.                     checkValue = 0;
  829.                 theMessage->WriteLong('FIGV', checkValue);
  830.         }
  831.         else if (theView->IsMemberClass(GetClassIDFromName("TPopup"))) {
  832.             short i = ((TPopup*) theView)->GetCurrentItem();    
  833.             ((TPopup*) theView)->GetItemText(i,configParam);
  834.                 
  835.             theMessage->WriteString('FIGV', configParam);
  836.         }
  837.  
  838.         FailInfo fi;
  839.         if (fi.Try())
  840.         {
  841.             theReplyEvent = theMessage->Send();    // Don't care if we fail
  842.             fi.Success();
  843.         }
  844.         else
  845.         {
  846.         }
  847.         
  848.         /* Set the parameter */ 
  849.         if (theReplyEvent) 
  850.             { 
  851.                 theReplyEvent->ReadString('FIGR', configParam);
  852.                 /* This is the result of the Configuration change */
  853.                 if (configParam.Length() != 0) {
  854.                     TWindow *    aWindow;
  855.                     IDType        dismisser;
  856.                     TStaticText* t;
  857.                     
  858.                     FailNIL(aWindow = gViewServer->NewTemplateWindow(1002, this));
  859.                     t = (TStaticText*) aWindow->FindSubView('MESS');
  860.                     if (t) {
  861.                         t->SetText(configParam, kRedraw);
  862.                         dismisser = aWindow->PoseModally();
  863.                     }
  864.                     aWindow->CloseAndFree();
  865.                     FailOSErr(-1);
  866.                 }
  867.             }
  868.         
  869.         theMessage = (TAppleEvent*)  FreeIfObject((TObject*) theMessage);
  870.         theReplyEvent = (TAppleEvent*)  FreeIfObject((TObject*) theReplyEvent);
  871. }
  872.  
  873. pascal void TDocumentSecondStomach::GetConfigValue(TView* theView) {
  874.         TAppleEvent* theMessage;
  875.         TAppleEvent* theReplyEvent = NULL;
  876.         CStr255 configParam;
  877.         short configIndex;
  878.         
  879.         const kConfigStringList = 7000;
  880.         
  881.         /* Get user value */
  882.         configIndex =theView->fUserArea;
  883.         
  884.         /* Get the config parameter name */
  885.         GetIndString(configParam,kConfigStringList,configIndex);
  886.  
  887.         FailNIL(theMessage = new TAppleEvent);
  888.         theMessage->IAppleEvent(kSSEventClass, 'gfig', fTargetAddress, kAEWaitReply);    
  889.         theMessage->WriteLong('SSID',fDocSessionID);
  890.         
  891.         /* Write config parameter to outgoing ae */ 
  892.         theMessage->WriteString('WFIG',configParam);
  893.         
  894.         FailInfo fi;
  895.         if (fi.Try())
  896.         {
  897.             theReplyEvent = theMessage->Send();    // Don't care if we fail
  898.             fi.Success();
  899.         }
  900.         else
  901.         {
  902.         }
  903.         
  904.         /* Set the parameter */ 
  905.         if (theReplyEvent) 
  906.             { 
  907.                 long checkValue;
  908.                 FailInfo fi;
  909.                 if (fi.Try())            // Might not get a value - if so leave field blank
  910.                 {
  911.                     if (theView->IsMemberClass(GetClassIDFromName("TEditText"))) {
  912.                             theReplyEvent->ReadString('FIGV', configParam);
  913.                             ((TEditText*) theView)->SetText(configParam,kRedraw);
  914.                     }
  915.                     else if (theView->IsMemberClass(GetClassIDFromName("TCheckBox"))) {
  916.                         checkValue = theReplyEvent->ReadLong('FIGV');
  917.                         if (checkValue == 1)
  918.                             ((TCheckBox*) theView)->SetState(true,kRedraw);
  919.                         else
  920.                             ((TCheckBox*) theView)->SetState(false,kRedraw);
  921.                     }
  922.                     else if (theView->IsMemberClass(GetClassIDFromName("TPopup"))) {
  923.                             TPopup* p;
  924.                             short i;
  925.                             CStr255 t;
  926.                             Boolean done = FALSE;
  927.                             
  928.                             p = (TPopup*) theView;
  929.                             p->SetCurrentItem(1, kRedraw);
  930.                             theReplyEvent->ReadString('FIGV', configParam);
  931.                             i = 2;
  932.                             while (!done) {
  933.                                 p->GetItemText(i,t);
  934.                                 if (RelString(t,configParam,FALSE,TRUE) == 0) {
  935.                                     p->SetCurrentItem(i, kRedraw);
  936.                                     done = TRUE;
  937.                                 }
  938.                                 i++;
  939.                             }
  940.  
  941.                     }
  942.                     
  943.                     fi.Success();
  944.                 }
  945.                 else 
  946.                 {
  947.                 }
  948.             }
  949.         
  950.         theMessage = (TAppleEvent*)  FreeIfObject((TObject*) theMessage);
  951.         theReplyEvent = (TAppleEvent*)  FreeIfObject((TObject*) theReplyEvent);
  952. }
  953.  
  954. /***********************************|****************************************/
  955.  
  956. pascal void TDocumentSecondStomach::SendAliveMessage()
  957.  
  958. {
  959.     // const kMinutesBetween = 1;
  960.     
  961.     // fSendAliveCounter++;
  962.     // if (fSendAliveCounter > kMinutesBetween * 4) {
  963.         TAppleEvent* theMessage;
  964.         FailNIL(theMessage = new TAppleEvent);
  965.         theMessage->IAppleEvent(kSSEventClass, 'alve', fTargetAddress, kAENoReply);        
  966.         theMessage->WriteLong('SSID',fDocSessionID);
  967.         FailInfo fi;
  968.         if (fi.Try())
  969.         {
  970.             theMessage->Send();    // Don't care if we fail
  971.             fi.Success();
  972.         }
  973.         else
  974.         {
  975.         }
  976.         
  977.         theMessage = (TAppleEvent*)  FreeIfObject((TObject*) theMessage);
  978.     //    fSendAliveCounter = 0;
  979.     // }
  980. }
  981.  
  982. /***********************************|****************************************/
  983.  
  984. pascal void TTimerHandler::ITimerHandler(TDocumentSecondStomach* parentDoc) {
  985.     fParentDoc = parentDoc;
  986.     fBaseTimer = TickCount();
  987.     this->IEventHandler(NULL);
  988. }
  989.  
  990. /***********************************|****************************************/
  991.  
  992. pascal Boolean TTimerHandler::DoIdle(IdlePhase)
  993.  
  994. {
  995.         fParentDoc->BlinkStatus();
  996.         
  997.         if (fParentDoc->TimerExpired()) {
  998.             OSErr err = fParentDoc->EstablishSession();    // This will fail out if cannot establish a session
  999.             if (err == noErr) {
  1000.                 fParentDoc->SendItemsToBeLogged();
  1001.             }
  1002.             else {
  1003.                 if (fParentDoc->fDisconnected == false) {
  1004.                     fParentDoc->MonitoringChange(true);
  1005.                     fParentDoc->AddToLog("Restart Monitoring");
  1006.                 }
  1007.             }
  1008.             fParentDoc->ResetTimer();
  1009.         }
  1010.         else {
  1011.             if ((TickCount() - fBaseTimer) > 3600) { // Every minute
  1012.                 fBaseTimer = TickCount();
  1013.                 fParentDoc->SendAliveMessage();
  1014.             }
  1015.         }
  1016.     
  1017.     return FALSE;
  1018. }
  1019. /***********************************|****************************************/
  1020.  
  1021. Boolean IsViewIdentifierAConfigItem ( IDType viewType )
  1022. {    unsigned long l = (unsigned long) viewType;
  1023.     char c1 = (char) ((l & (unsigned long) 0xff000000) >> 24);
  1024.  
  1025.     Boolean result = (c1 == 'C');
  1026.     
  1027.     return result;
  1028. }
  1029.  
  1030. /***********************************|****************************************/
  1031.  
  1032. pascal void SendConfigChange(TView* theSubView, void* staticLink)
  1033. {
  1034.     CStr255 info;
  1035.     
  1036.     if (IsViewIdentifierAConfigItem (theSubView->fIdentifier))
  1037.     {
  1038.             TDocumentSecondStomach* s = (TDocumentSecondStomach*) staticLink;
  1039.             s->SendConfigMessage(theSubView);
  1040.     }
  1041.     else
  1042.     {
  1043.     }
  1044.  
  1045.     theSubView->EachSubView (SendConfigChange, (void*) staticLink );
  1046. }
  1047.  
  1048. /***********************************|****************************************/
  1049.  
  1050. pascal void TDialogViewConfig::DoEvent(EventNumber eventNumber, TEventHandler* source,
  1051.                                 TEvent* event)//Override
  1052. {
  1053.     if  (source->fIdentifier == 'SAVE') {
  1054.         FailInfo fi;
  1055.         if (fi.Try())
  1056.         {
  1057.             TDocumentSecondStomach* s = (TDocumentSecondStomach*) fDocument;
  1058.  
  1059.             EachSubView (SendConfigChange, (void*) s);
  1060.             
  1061.             inherited::DoEvent(eventNumber,source,event);
  1062.             fi.Success();
  1063.         }
  1064.         else
  1065.         {
  1066.             // Bad Config parameter
  1067.             // Leave the dialog up
  1068.         }
  1069.     }
  1070.     else
  1071.         inherited::DoEvent(eventNumber,source,event);
  1072. }
  1073.  
  1074. /***********************************|****************************************/
  1075.  
  1076. pascal void SetConfigStringFromServer(TView* theSubView, void* staticLink)
  1077. {
  1078.     CStr255 info;
  1079.     
  1080.     if (IsViewIdentifierAConfigItem ( theSubView->fIdentifier ) )
  1081.     {
  1082.         TDocumentSecondStomach* s = (TDocumentSecondStomach*) staticLink;
  1083.  
  1084.         s->GetConfigValue(theSubView);
  1085.     }
  1086.     else
  1087.     {
  1088.     }
  1089.  
  1090.     theSubView->EachSubView (SetConfigStringFromServer, (void*) staticLink );
  1091. }
  1092.  
  1093. pascal void TDialogViewConfig::Open()
  1094. {
  1095.         TDocumentSecondStomach* s = (TDocumentSecondStomach*) fDocument;
  1096.  
  1097.         EachSubView (SetConfigStringFromServer, (void*) s);
  1098.         
  1099.         inherited::Open();
  1100. }